package waal.pc.backend.module;

import waal.pc.backend.channels.Channel;
import waal.pc.backend.channels.DigitalChannel;
import waal.pc.backend.channels.DigitalOutputChannel;
import waal.pc.backend.hub.Hub;

public class ModuleDigital extends Module {


	private DigitalChannel[] allChannels;
	private DigitalChannel[] inChannels;
	private DigitalOutputChannel[] outChannels;
	
	private boolean[] switchable;
	
	public ModuleDigital(Hub hub, int number, boolean active, String name) {
		super(hub, number, active, name , 0xDF);
	}

	public void initModule(boolean active, int channels, int activeChannels, int inOut, int switchable, long minTimeBase, double min, double max, String unit, String[] channelNames) {
		this.initModule(active, channels, 1, minTimeBase, min, max, unit);
		this.switchable = new boolean[channels];
		this.allChannels = new DigitalChannel[channels];
		this.inChannels = new DigitalChannel[channels]; 
		this.outChannels = new DigitalOutputChannel[channels];
		
		
		int mask;
		for(int i = 0; i < channels; i++) {
			mask = (1 << i);
			
			if((activeChannels & mask) > 0) {
				this.activeChannels[i] = true;
			} else {
				this.activeChannels[i] = false;
			}
			
			if((switchable & mask ) > 0) {	this.switchable[i] = true;} 
				else {	this.switchable[i] = false; }
			if((inOut & mask ) > 0) {
				this.hasInput = true;
				this.input[i] = true;
				this.inChannels[i] = new DigitalChannel(this, i, channelNames[i]);
				this.inChannelSet.add(this.inChannels[i]);
				this.allChannelSet.add(this.inChannels[i]);
				this.allChannels[i] = this.inChannels[i];
			} else {
				this.hasOutput = true;
				this.input[i] = false;
				this.outChannels[i] = new DigitalOutputChannel(this, i, channelNames[i]);
				this.outChannelSet.add(this.outChannels[i]);
				this.allChannelSet.add(this.outChannels[i]);
				this.allChannels[i] = this.outChannels[i];
			}
		}
		
		this.initilized = true;
		this.getStatus();
		this.fireModuleEvent(5);
	}
	
	public boolean isDigital() {
		return true;
	}
	
	public void processData(double time, int value) {
		//Log.addToDebug(2, "ModuleDigital", "processData", "Data for Module: " + this.moduleNumber + " Data: 0x" + value + "(" + Integer.toBinaryString(value) + ")" );
		int mask;
		boolean state;
		// get State for each Channel
		for(int i = 0; i < this.allChannels.length; i++) {
			mask = (1 << i);
			if((value & mask) > 0) {
				state = true;
			} else {
				state = false;
			}
			if(this.activeChannels[i]) {
				this.allChannels[i].addValue(time, state);
			} else {
				this.allChannels[i].setValue(state);
			}
		}
	}
		
	public void processConfig(int[] data) {
		//int ch = data[2];
		switch(data[3]) {
		case 0xFC: //Get Status
			int mask;
			boolean state;
			for(int i = 0; i < this.allChannels.length; i++) {
				mask = (1 << i);
				if((data[4] & mask) > 0) {
					state = true;
				} else {
					state = false;
				}
				if(this.input[i])  {// Input
					this.inChannels[i].setValue(state);
				} else {
					this.outChannels[i].setValue(state);
				}
			}
			break;
		}
	}
		
	private void getStatus() {
		this.SendConfig(0, 0xFC);
	}
	/*
	private void setChannelActive(int value) {
		for(int i = 0; i < this.allChannels.length; i++) {
			if((value & (1 << i)) > 0) {
				this.setChannelActive(i, true);
			} else {
				this.setChannelActive(i, false);
			}
		}
	}
	
	private void setChannelActive(int ch, boolean value) {
		if(value != this.isChannelActive(ch)) {
			this.activeChannels[ch] = value;
		}
	}*/

	@Override
	public void setChannelName(int ch, String name) {
		this.allChannels[ch].setName(name);
	}

	@Override
	public void sendChannelActive(int ch, boolean value) {
		if(value) {
			this.SendConfig(ch, 0xFF, 1);
		} else {
			this.SendConfig(ch, 0xFF, 0);
		}
	}

	@Override
	public void updateValues() {
		this.getStatus();		
	}

	@Override
	public Channel getChannel(int number) {
		//TODO Check
		System.out.println("ask for Channel: " + number);
		return this.allChannels[number];
	}		
}
